package org.yonsei.iwb.sdt.ontology;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.yonsei.iwb.sdt.SDTLearner;

public class UnitClassModel {
    
    public static boolean BACKWARD = false;
    public static boolean FORWARD = true;
    private Resource centerclass;
    private Model model;
    private Vector<Resource> dataTypeProperty;
    private Vector<PropertyArc> objectProperty;
    private Vector<Resource> uniqResource;

    public UnitClassModel(Resource r, Model model) {
        this.centerclass = r;
        this.model = model;
        this.dataTypeProperty = new Vector();
        this.objectProperty = new Vector();
        this.uniqResource = new Vector();
        
        findConnectedProperty(r);
        NodeIterator resit = model.listObjectsOfProperty(centerclass, RDFS.subClassOf);
        while (resit.hasNext()) {
            Resource superclass = resit.nextNode().asResource();
            findConnectedProperty(superclass);
        }
    }

    private void findConnectedProperty(Resource r) {
        ResIterator iter2 = model.listResourcesWithProperty(RDFS.domain, r);
        while (iter2.hasNext()) {
            Resource forwardp = iter2.nextResource();
            
            if(UncountedResources.SET.contains(forwardp)){
                continue;
            }
            
            StmtIterator iter3 = model.listStatements(forwardp, RDF.type, OWL.DatatypeProperty);
            if (iter3.hasNext()) {
                if (!this.containsDatatypeProperty(forwardp.asResource())) {
                    this.dataTypeProperty.add(forwardp.asResource());
                }
            }
            
            StmtIterator iter4 = model.listStatements(forwardp, RDF.type, OWL.ObjectProperty);
            if (iter4.hasNext()) {
                if (!this.containsObjectProperty(forwardp.asResource())) {
//                    System.out.println(r.getLocalName()+"  has forward : " + forwardp.getLocalName());
                    this.objectProperty.add(new PropertyArc(forwardp.asResource(), UnitClassModel.FORWARD));
                }
            }
        }
        
        ResIterator resi = model.listResourcesWithProperty(RDFS.range, r);
        while(resi.hasNext()){
            Resource reversep = resi.nextResource();
            if(UncountedResources.SET.contains(reversep)){
                continue;
            }
            StmtIterator iter4 = model.listStatements(reversep, RDF.type, OWL.ObjectProperty);
            if (iter4.hasNext()) {                
                if (!this.containsObjectProperty(reversep.asResource())) {
//                    System.out.println("reverse : " + reversep.getLocalName()+"  ->  "+ r.getLocalName());
                    this.objectProperty.add(new PropertyArc(reversep.asResource(), UnitClassModel.BACKWARD));
                }
            }
        }        
        
        if(SDTLearner.TARGETPROPERTY != null){
            this.dataTypeProperty.remove(SDTLearner.TARGETPROPERTY.asResource());
        }        
    }

    public boolean containsObjectProperty(Resource r) {
        for (int i = 0; i < this.objectProperty.size(); i++) {
            PropertyArc pa = this.objectProperty.get(i);
            if(pa.equals(r)){
                return true;                
            }
        }
        return false;
    }

    public boolean containsDatatypeProperty(Resource r) {
        return this.dataTypeProperty.contains(r);
    }
    
//    public Enumeration<Resource> getObjectPropertyKeySet(){
//        return this.objectProperty.keys();
//    }
    
    public Vector<Resource> getDatatypePropertySet(){
        return this.dataTypeProperty;
    }
    
    public Vector<PropertyArc> getObjectPropertySet(){
        return this.objectProperty;
    }

    public void printUnitClassModel() {
        System.out.println("Class : " + centerclass);
        for (int i = 0; i < this.dataTypeProperty.size(); i++) {
            System.out.println("Datatype Property : " + this.dataTypeProperty.get(i));
        }

        for (int i = 0; i < this.objectProperty.size(); i++) {
            System.out.println("Object Property : " + this.objectProperty.get(i));
        }
    }
}
